package common.core.domain.udp;

import com.alibaba.fastjson.JSONObject;
import common.core.constans.StatusCode;
import common.core.domain.R;
import common.core.util.PropertiesUtil;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;

@Slf4j
public class UdpApiHandler {
    public static Object process(ChannelHandlerContext ctx, InetSocketAddress remoteAddress, JSONObject buffer){
        UdpApiProtocol apiProtocol = new UdpApiProtocol(ctx,remoteAddress,buffer);

        if (apiProtocol.getApiName() == null) {
            return R.failed(StatusCode.API_NOT_FOUND);
        }

        return invoke(apiProtocol.getApiName(),apiProtocol);
    }

    public static Object invoke(String apiName, UdpApiProtocol apiProtocol){
        Class<?> classname;
        Object   classObject;
        Constructor constructor;
        Method method;
        Object   result = null;

        UdpApi api = UdpApiRoute.apiMap.get(apiName);
        if(api == null){
            return R.failed(StatusCode.API_NOT_FOUND);
        }

        if(!api.getVersion().equals(apiProtocol.getVersion())){
            return R.failed(StatusCode.API_VERSION_NOT_MATCH);
        }

        if(api.getMethod() != null && !api.getMethod().contains(apiProtocol.getMethod())){
            return R.failed(StatusCode.REQUEST_MODE_ERROR);
        }

        try {
            classname = Class.forName(PropertiesUtil.getString("handler.package.name") + "." + api.getHandler());
            constructor = classname.getConstructor(UdpApiProtocol.class);
            classObject = constructor.newInstance(apiProtocol);
        } catch (NoSuchMethodException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        } catch (ClassNotFoundException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        } catch (InvocationTargetException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        } catch (InstantiationException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        } catch (IllegalAccessException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        }

        try {
            method = classname.getMethod(apiProtocol.getMethod().toString());
        } catch (NoSuchMethodException e) {
            log.error(e.getMessage());
            return R.failed(StatusCode.API_SERVER_ERROR);
        }

        try {
            result = method.invoke(classObject);
        } catch (InvocationTargetException e) {
            log.error(e.getMessage());
        } catch (IllegalAccessException e) {
            log.error(e.toString());
        }

        return result;
    }
}
